package com.gitee.cashzhang27.test.boot.graphql.webflux.graphql.components;

import com.gitee.cashzhang27.test.boot.graphql.webflux.graphql.ExecutionInputCustomizer;
import com.gitee.cashzhang27.test.boot.graphql.webflux.graphql.GraphQLInvocation;
import com.gitee.cashzhang27.test.boot.graphql.webflux.graphql.GraphQLInvocationData;
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.Internal;
import org.dataloader.DataLoaderRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Internal
@Component
public class DefaultGraphQLInvocation implements GraphQLInvocation {

  @Autowired(required = false)
  private GraphQL graphQL;

  @Autowired(required = false)
  private DataLoaderRegistry dataLoaderRegistry;

  @Autowired
  private ExecutionInputCustomizer executionInputCustomizer;

  @Override
  public Mono<ExecutionResult> invoke(GraphQLInvocationData invocationData,
      ServerWebExchange serverWebExchange) {
    ExecutionInput.Builder executionInputBuilder = ExecutionInput.newExecutionInput()
        .query(invocationData.getQuery())
        .operationName(invocationData.getOperationName())
        .variables(invocationData.getVariables());
    if (dataLoaderRegistry != null) {
      executionInputBuilder.dataLoaderRegistry(dataLoaderRegistry);
    }
    ExecutionInput executionInput = executionInputBuilder.build();
    Mono<ExecutionInput> customizedExecutionInputMono = executionInputCustomizer
        .customizeExecutionInput(executionInput, serverWebExchange);
    return customizedExecutionInputMono.flatMap(customizedExecutionInput -> Mono
        .fromCompletionStage(graphQL.executeAsync(customizedExecutionInput)));
  }

}
